﻿using System;
using System.IO;

using System.Windows.Controls;
using System.Windows.Media;
using Microsoft.VisualStudio.Text.Editor;
using System.Windows.Media.Imaging;
using System.Windows.Threading;

using Epic;

namespace KyuuBackground
{
    class KyuuBackground
    {
        private static ImageBrush smImageBrush = new ImageBrush();

        static KyuuBackground()
        {
            RefreshBackgroundBrush();
            KyuuBackgroundConfigurationManager.ConfigurationUpdated += WatchForBrushes;
        }

        private static void WatchForBrushes(object sender, EventArgs e)
        {
            smImageBrush.Dispatcher.BeginInvoke(new Action(RefreshBackgroundBrush));
        }

        private static void RefreshBackgroundBrush()
        {
            smImageBrush.ImageSource = null;

            try
            {
                if (string.IsNullOrWhiteSpace(KyuuBackgroundConfigurationManager.Section.Picture.Source))
                    return;

                var source = new BitmapImage();
                // have to be done in this way to get rid of file sharing problem
                source.BeginInit();
                source.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
                source.CacheOption = BitmapCacheOption.OnLoad;
                source.UriSource = new Uri(Path.Combine(KyuuBackgroundConfigurationManager.SettingsBase, KyuuBackgroundConfigurationManager.Section.Picture.Source));
                source.EndInit();

                smImageBrush.ImageSource = source;

                smImageBrush.Stretch = (Stretch)KyuuBackgroundConfigurationManager.Section.Picture.ScaleMode;
                smImageBrush.AlignmentX = (AlignmentX)KyuuBackgroundConfigurationManager.Section.Picture.AlignmentX;
                smImageBrush.AlignmentY = (AlignmentY)KyuuBackgroundConfigurationManager.Section.Picture.AlignmentY;
            }
            catch { }
        }

        private Canvas mImageSurface; // using Canvas instead of Image so all the controls can use a single brush
        private IWpfTextView mTextView;
        private IAdornmentLayer mAdornmentLayer;

        public KyuuBackground(IWpfTextView view)
        {
            mTextView = view;
            mAdornmentLayer = mTextView.GetAdornmentLayer(KyuuBackgroundFactory.AdornmentLayerName);

            RefreshLayerOpacity();
            KyuuBackgroundConfigurationManager.ConfigurationUpdated += WatchForLayerOpacity;
            mTextView.Closed += TextView_Closed;

            mTextView.LayoutChanged += TextView_LayoutChanged;
            InitializeImageAdornment();
        }

        private void TextView_Closed(object sender, EventArgs e)
        {
            // cleaning up event handler for text editor instances
            KyuuBackgroundConfigurationManager.ConfigurationUpdated -= WatchForLayerOpacity;
        }

        private void WatchForLayerOpacity(object sender, EventArgs e)
        {
            var @do = mAdornmentLayer as DispatcherObject;
            if (@do != null)
            {
                @do.Dispatcher.BeginInvoke(new Action(RefreshLayerOpacity));
            }
            else
            {
                RefreshLayerOpacity();
            }
        }

        private void RefreshLayerOpacity()
        {
            try
            {
                mAdornmentLayer.Opacity = KyuuBackgroundConfigurationManager.Section.Opacity;
            }
            catch { }
        }

        private void InitializeImageAdornment()
        {
            mImageSurface = new Canvas();
            RenderOptions.SetBitmapScalingMode(mImageSurface, BitmapScalingMode.Linear); // better look

            mImageSurface.Background = smImageBrush;

            mAdornmentLayer.AddAdornment(AdornmentPositioningBehavior.ViewportRelative, null, null, mImageSurface, null);
        }

        private void TextView_LayoutChanged(object sender, TextViewLayoutChangedEventArgs e)
        {
            Canvas.SetLeft(mImageSurface, mTextView.ViewportLeft);
            Canvas.SetTop(mImageSurface, mTextView.ViewportTop);

            mImageSurface.Width = mTextView.ViewportWidth;
            mImageSurface.Height = mTextView.ViewportHeight;
        }
    }
}
